package de.doegel.common.util;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.sql.SQLException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.Vector;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences.Editor;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Environment;
import android.preference.PreferenceManager;
import android.text.Html;
import android.text.SpannableStringBuilder;
import android.text.TextUtils;
import android.text.style.ClickableSpan;
import android.text.style.UnderlineSpan;
import android.util.Log;
import android.util.Pair;
import android.view.View;
import de.doegel.common.AbstractDatabaseHelper;
import de.doegel.common.IDoegelConstants;
import de.doegel.common.R;
import de.doegel.common.model.Contact;
import de.doegel.common.model.IncomingMessage;
import de.doegel.common.widget.HeadedContactItem;

public class Utils {
	public static void copyStream(InputStream in, OutputStream out) {
		final int buffer_size = 1024;
		try {
			byte[] bytes = new byte[buffer_size];
			for (;;) {
				int count = in.read(bytes, 0, buffer_size);
				if (count == -1)
					break;
				out.write(bytes, 0, count);
			}
		} catch (Exception ex) {
		} finally {
			try {
				in.close();
			} catch (Exception ex) {
			}
		}
	}

	public static byte[] copyStreamToByteArray(InputStream in) {
		ByteArrayOutputStream out = new ByteArrayOutputStream();
		copyStream(in, out);
		byte[] buffer = out.toByteArray();
		if (buffer.length == 0)
			return null;
		return buffer;
	}

	public static String parseAndFormatDate(String date, String parser, String formatter) {
		if (TextUtils.isEmpty(date))
			return "";

		SimpleDateFormat dateparser = new SimpleDateFormat(parser);
		SimpleDateFormat dateformatter = new SimpleDateFormat(formatter);
		String formattedDate = "";
		try {
			formattedDate = dateformatter.format(dateparser.parse(date));
		} catch (Exception e) {
			formattedDate = date;
		}
		return formattedDate;
	}

	public static String parseAndFormatDate1(String date, boolean person) {
		if (date == null) {
			return "";
		}
		SimpleDateFormat dateparser = person ? new SimpleDateFormat("yyyy-MM-dd") : new SimpleDateFormat("dd-MM-yyyy");
		SimpleDateFormat dateformatter = new SimpleDateFormat("dd. MMMMM yyyy");
		String formatedDate = "";
		try {
			String temp = date.replace(':', '-').replace('.', '-');
			formatedDate = dateformatter.format(dateparser.parse(temp));
		} catch (Exception e) {
			formatedDate = date;
		}
		return formatedDate;
	}

	public static String parseAndFormatNewsDate(Context context, String parserFormat, String date) {
		if (date == null) {
			return "";
		}
		String string = "";
		SimpleDateFormat dateparser = new SimpleDateFormat(parserFormat);

		try {
			Date newsDate = dateparser.parse(date);
			Date now = new Date();
			long offset = now.getTime() - newsDate.getTime();
			long diffDays = offset / (24 * 60 * 60 * 1000);
			if (diffDays > 0) {
				if (diffDays == 1) {
					string = diffDays + " " + context.getString(R.string.news_day_old);
				} else {
					string = diffDays + " " + context.getString(R.string.news_days_old);
				}
			} else {
				long diffHours = offset / (60 * 60 * 1000);

				if (diffHours > 0) {
					if (diffHours == 1) {
						string = diffHours + " " + context.getString(R.string.news_hour_old);
					} else {
						string = diffHours + " " + context.getString(R.string.news_hours_old);
					}
				} else {
					long diffMinutes = offset / (60 * 1000);
					if (diffMinutes > 0) {
						if (diffMinutes == 1) {
							string = diffMinutes + " " + context.getString(R.string.news_minute_old);
						} else {
							string = diffMinutes + " " + context.getString(R.string.news_minutes_old);
						}
					}
				}
			}
		} catch (ParseException e1) {
			e1.printStackTrace();
		}
		return string;
	}

	public static void sleep(long time) {
		try {
			Thread.sleep(time);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}

	public static String getMD5String(String str, String salt) {
		String hash = null;
		/*try {
			MessageDigest md5 = MessageDigest.getInstance("MD5");
			md5.reset();
			md5.update(hash.getBytes());
			hash = new BigInteger(1, md5.digest()).toString(16);
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		}*/		
		hash = md5(str);
		hash = hash + salt;
		hash = md5(hash);
		Log.i("--login hash--", hash);
		return hash;
	}

	public static String md5(String string) {
		byte[] hash;

		try {
			hash = MessageDigest.getInstance("MD5").digest(string.getBytes("ISO-8859-1"));
		} catch (NoSuchAlgorithmException e) {
			throw new RuntimeException("Huh, MD5 should be supported?", e);
		} catch (UnsupportedEncodingException e) {
			throw new RuntimeException("Huh, UTF-8 should be supported?", e);
		}

		StringBuilder hex = new StringBuilder(hash.length * 2);
		for (byte b : hash) {
			if ((b & 0xFF) < 0x10)
				hex.append("0");
			hex.append(Integer.toHexString(b & 0xFF));
		}
		return hex.toString();
	}

	public static String getSHA256String(String str, String salt) {
		String hash = null;
		try {
			MessageDigest sha256 = MessageDigest.getInstance("SHA-256");
			sha256.reset();
			sha256.update((str + salt).getBytes());
			hash = new BigInteger(1, sha256.digest()).toString(16);
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		}
		return hash;
	}

	public static Intent createAnimalIntent(Context context, int animalId, String animalName, String animalRace, String animalOwner) {
		return createAnimalIntent(context, animalId, animalName, animalRace, animalOwner, false);
	}

	public static Intent createAnimalIntent(Context context, int animalId, String animalName, String animalRace, String animalOwner, boolean ownerSelectable) {
		if (animalId < 0)
			return null;
		Intent intent = new Intent(context, getActivityClass(context, "AnimalDetailsActivity"));
		intent.putExtra(IDoegelConstants.ANIMAL_ID_EXTRA, animalId);
		if (!TextUtils.isEmpty(animalName)) {
			intent.putExtra(IDoegelConstants.ANIMAL_NAME_EXTRA, animalName);
		}
		if (!TextUtils.isEmpty(animalRace)) {
			intent.putExtra(IDoegelConstants.ANIMAL_RACE_EXTRA, animalRace);
		}
		if (!TextUtils.isEmpty(animalOwner)) {
			intent.putExtra(IDoegelConstants.ANIMAL_OWNER_EXTRA, animalOwner);
		}
		intent.putExtra(IDoegelConstants.NOT_SELECTABLE_ANIMAL_OWNER_EXTRA, ownerSelectable);
		return intent;
	}

	public static Intent createPersonIntent(Context context, int personId, String personName) {
		return createPersonIntent(context, personId, personName, -1);
	}

	public static Intent createPersonIntent(Context context, int personId, String personName, int nonSelectableAnimalId) {
		if (personId < 0)
			return null;
		Intent intent = new Intent(context, getActivityClass(context, "PersonDetailsActivity"));
		intent.putExtra(IDoegelConstants.PERSON_ID_EXTRA, personId);
		if (!TextUtils.isEmpty(personName)) {
			intent.putExtra(IDoegelConstants.PERSON_NAME_EXTRA, personName);
		}
		if (nonSelectableAnimalId > 0) {
			intent.putExtra(IDoegelConstants.NOT_SELECTABLE_ANIMAL_ID_EXTRA, nonSelectableAnimalId);
		}
		return intent;
	}

	public static Intent createMessageIntent(Context context, boolean inbox, int messageId) {
		if (messageId < 0)
			return null;
		Intent intent = new Intent(context, getActivityClass(context, "MessageDetailsActivity"));
		intent.putExtra(IDoegelConstants.IS_INBOX_EXTRA, inbox);
		intent.putExtra(IDoegelConstants.MESSAGE_ID_EXTRA, messageId);
		return intent;
	}

	public static Intent createHomeIntent(Context context) {
		Intent intent = new Intent(context, getActivityClass(context, "MainActivity"));
		intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
		return intent;
	}

	public static Intent createSettingsIntent(Context context) {
		Intent intent = new Intent(context, getActivityClass(context, "SettingsActivity"));
		return intent;
	}

	public static Intent createInfoIntent(Context context) {
		Intent intent = new Intent(context, getActivityClass(context, "InfoActivity"));
		return intent;
	}

	public static Intent createContactsIntent(Context context) {
		Intent intent = new Intent(context, getActivityClass(context, "ContactsActivity"));
		return intent;
	}

	public static Intent createContactSearchIntent(Context context) {
		Intent intent = new Intent(context, getActivityClass(context, "ContactSearchActivity"));
		return intent;
	}

	public static Intent createAnimalHistoryAndFavoritesIntent(Context context) {
		Intent intent = new Intent(context, getActivityClass(context, "AnimalHistoryAndFavoritesActivity"));
		return intent;
	}

	public static Intent createAnimalSearchIntent(Context context) {
		Intent intent = new Intent(context, getActivityClass(context, "AnimalSearchActivity"));
		return intent;
	}

	public static Intent createMessagesIntent(Context context) {
		Intent intent = new Intent(context, getActivityClass(context, "MessagesActivity"));
		return intent;
	}

	public static Intent createComposeMessageIntent(Context context) {
		Intent intent = new Intent(context, getActivityClass(context, "MessageComposeActivity"));
		return intent;
	}

	public static Intent createNewsIntent(Context context) {
		Intent intent = new Intent(context, getActivityClass(context, "NewsActivity"));
		return intent;
	}

	public static Intent createVideoIntent(Context context, String videoUrl) {
		Intent intent = new Intent(Intent.ACTION_VIEW);
		intent.setDataAndType(Uri.parse(videoUrl), "video/*");
		return intent;
	}

	public static Intent createComposeMessageIntent(Context context, int personId, String personName, String subject, String content) {
		Intent intent = new Intent(context, getActivityClass(context, "MessageComposeActivity"));
		if (personId > 0) {
			intent.putExtra(IDoegelConstants.PERSON_ID_EXTRA, personId);
		}
		if (!TextUtils.isEmpty(personName)) {
			intent.putExtra(IDoegelConstants.PERSON_NAME_EXTRA, personName);
		}
		if (!TextUtils.isEmpty(subject)) {
			intent.putExtra(IDoegelConstants.MESSAGE_SUBJECT_EXTRA, subject);
		}
		if (!TextUtils.isEmpty(content)) {
			intent.putExtra(IDoegelConstants.MESSAGE_CONTENT_EXTRA, content);
		}
		return intent;
	}

	public static Intent createBreedIntent(Context context, int breedId) {
		if (breedId < 0)
			return null;
		Intent intent = new Intent(context, getActivityClass(context, "BreedDetailsActivity"));
		intent.putExtra(IDoegelConstants.BREED_ID_EXTRA, breedId);
		return intent;
	}

	public static Intent createEmailIntent(String email) {
		if (TextUtils.isEmpty(email))
			return null;
		Intent intent = new Intent(Intent.ACTION_SEND);
		intent.setType("plain/text");
		intent.putExtra(android.content.Intent.EXTRA_EMAIL, new String[] { email });
		return intent;
	}

	public static Intent createWebIntent(String url) {
		if (TextUtils.isEmpty(url))
			return null;
		url = url.toLowerCase();
		if (!url.startsWith("http://") && !url.startsWith("https://")) {
			url = "http://" + url;
		}
		Intent intent = null;
		try {
			intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
		} catch (Exception e) {
			e.printStackTrace();
		}
		return intent;
	}

	public static Intent createPhoneIntent(String phonenumber) {
		if (TextUtils.isEmpty(phonenumber))
			return null;
		Intent intent = null;
		try {
			intent = new Intent(Intent.ACTION_VIEW, Uri.parse("tel:" + phonenumber));
		} catch (Exception e) {
			e.printStackTrace();
		}
		return intent;
	}

	public static Intent createMapIntent(String street) {
		if (TextUtils.isEmpty(street))
			return null;
		String temp = street.replace(',', ' ').trim();
		if (TextUtils.isEmpty(temp))
			return null;
		Intent intent = null;
		try {
			intent = new Intent(Intent.ACTION_VIEW, Uri.parse("geo:0,0?q=" + street));
		} catch (Exception e) {
			e.printStackTrace();
		}
		return intent;
	}

	public static void showAlertDialog(Context context, String title, String message) {
		AlertDialog.Builder builder = new AlertDialog.Builder(context);
		builder.setMessage(message).setCancelable(true).setNeutralButton(context.getString(R.string.dialog_close), new DialogInterface.OnClickListener() {
			@Override
			public void onClick(DialogInterface dialog, int which) {
				dialog.dismiss();
			}
		});
		if (title != null) {
			builder.setTitle(title);
		}
		builder.create().show();
	}

	public static SpannableStringBuilder makeClickable(final Context context, String htmltext, final Intent intent) {
		SpannableStringBuilder stringBuilder = new SpannableStringBuilder(Html.fromHtml(htmltext));
		UnderlineSpan[] underlines = stringBuilder.getSpans(0, stringBuilder.length(), UnderlineSpan.class);
		for (UnderlineSpan span : underlines) {
			int start = stringBuilder.getSpanStart(span);
			int end = stringBuilder.getSpanEnd(span);
			int flags = stringBuilder.getSpanFlags(span);
			ClickableSpan myActivityLauncher = new ClickableSpan() {
				public void onClick(View view) {
					context.startActivity(intent);
				}
			};
			stringBuilder.setSpan(myActivityLauncher, start, end, flags);
		}
		return stringBuilder;
	}

	public static void showMessageReceivedNotification(Context applicationContext, IncomingMessage message) {
		int unreadMessageCount = Utils.getUnreadMessageCount(applicationContext);
		unreadMessageCount++;

		String tickerText = applicationContext.getString(R.string.notification_ticker_1_message);
		String contentTitle = message.fromtoName;
		String contentText = message.subject;
		long when = System.currentTimeMillis();
		try {
			when = new SimpleDateFormat("yyyy:MM:dd:hh:mm").parse(message.date).getTime();
		} catch (ParseException e) {
			e.printStackTrace();
		}
		if (unreadMessageCount > 1) {
			tickerText = unreadMessageCount + " " + applicationContext.getString(R.string.notification_ticker_n_message);
			contentTitle = applicationContext.getString(R.string.app_name);
			contentText = unreadMessageCount + " " + applicationContext.getString(R.string.notification_content);
		}

		showNotification(applicationContext, 1, tickerText, contentTitle, contentText, when, message.id);

		Utils.setUnreadMessageCount(applicationContext, unreadMessageCount);
	}

	public static void showNotification(Context applicationContext, int notificationId, String tickerText, String contentTitle, String contentText, long when,int id) {
		String ns = Context.NOTIFICATION_SERVICE;
		NotificationManager mNotificationManager = (NotificationManager) applicationContext.getSystemService(ns);

		int icon = R.drawable.notification_icon;
		Notification notification = new Notification(icon, tickerText, when);

		notification.flags |= Notification.FLAG_AUTO_CANCEL;
		notification.sound = Uri.parse("android.resource://" + applicationContext.getResources().getResourcePackageName(R.raw.notification_sound) + "/" + R.raw.notification_sound);
		notification.defaults |= Notification.DEFAULT_VIBRATE;
		notification.defaults |= Notification.DEFAULT_LIGHTS;

		Context context = applicationContext;
		Intent notificationIntent = new Intent(context, getActivityClass(applicationContext, "MessagesActivity"));
		notificationIntent.putExtra("id", id);
		notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP/*
																 * | Intent.
																 * FLAG_ACTIVITY_NEW_TASK
																 */);
		PendingIntent contentIntent = PendingIntent.getActivity(context, 0, notificationIntent, 0);
		notification.setLatestEventInfo(applicationContext, contentTitle, contentText, contentIntent);

		mNotificationManager.notify(notificationId, notification);
	}

	public static boolean writeBitmapIntoSD(Context context, Bitmap bitmap) {
		try {
			FileOutputStream out = new FileOutputStream(getTemporaryImageFile(context));
			bitmap.compress(Bitmap.CompressFormat.PNG, 90, out);
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}
		return true;
	}

	public static List<HeadedContactItem> createItems(AbstractDatabaseHelper databaseHelper) {
		List<HeadedContactItem> contactItems = new Vector<HeadedContactItem>();
		try {
			List<Contact> contacts = databaseHelper.getContactDao().queryForAll();
			if (contacts != null) {
				Collections.sort(contacts, new Comparator<Contact>() {
					public int compare(Contact c1, Contact c2) {
						return c1.name.toLowerCase().compareTo(c2.name.toLowerCase());
					}
				});
				for (int i = 0; i < contacts.size(); i++) {
					Contact contact = contacts.get(i);
					HeadedContactItem item = new HeadedContactItem(contact.name);
					item.setTag(contact);
					contactItems.add(item);
				}
			}

		} catch (SQLException e) {
			e.printStackTrace();
		}
		return contactItems;
	}

	public static String convertRole2string(Context context, int role) {
		String rank = "";
		switch (role) {
		case 1:
			rank = context.getString(R.string.person_role_classic);
			break;
		case 2:
			rank = context.getString(R.string.person_role_moderator);
			break;
		case 3:
			rank = context.getString(R.string.person_role_administrator);
			break;
		case 4:
			rank = context.getString(R.string.person_role_premium);
			break;
		default:
			rank = context.getString(R.string.person_role_nologin);
		}
		return rank;
	}

	public static int getUnreadMessageCount(Context context) {
		return PreferenceManager.getDefaultSharedPreferences(context.getApplicationContext()).getInt(IDoegelConstants.UNREAD_MESSAGES_COUNT_PREFERENCE, 0);
	}

	public static synchronized void setUnreadMessageCount(Context context, int count) {
		Editor editor = PreferenceManager.getDefaultSharedPreferences(context.getApplicationContext()).edit();
		editor.putInt(IDoegelConstants.UNREAD_MESSAGES_COUNT_PREFERENCE, count);
		editor.commit();
	}

	public static synchronized Pair<String, String> getAccountData(Context context) {
		String username = PreferenceManager.getDefaultSharedPreferences(context.getApplicationContext()).getString(IDoegelConstants.USERNAME_PREFERENCE, null);
		String password = PreferenceManager.getDefaultSharedPreferences(context.getApplicationContext()).getString(IDoegelConstants.PASSWORD_PREFERENCE, null);
		if (TextUtils.isEmpty(username) || TextUtils.isEmpty(password)) {
			return null;
		}
		return new Pair<String, String>(username, password);
	}

	public static synchronized void setAccountData(Context context, String username, String password) {
		Editor editor = PreferenceManager.getDefaultSharedPreferences(context.getApplicationContext()).edit();
		editor.putString(IDoegelConstants.USERNAME_PREFERENCE, username);
		editor.putString(IDoegelConstants.PASSWORD_PREFERENCE, password);
		editor.commit();
	}

	public static synchronized int getUserRole(Context context) {
		return PreferenceManager.getDefaultSharedPreferences(context.getApplicationContext()).getInt(IDoegelConstants.USERROLE_PREFERENCE, 0);
	}

	public static synchronized void setUserRole(Context context, int userrole) {
		Editor editor = PreferenceManager.getDefaultSharedPreferences(context.getApplicationContext()).edit();
		editor.putInt(IDoegelConstants.USERROLE_PREFERENCE, userrole);
		editor.commit();
	}

	public static synchronized void setFirstStart(Context context) {
		Editor editor = PreferenceManager.getDefaultSharedPreferences(context.getApplicationContext()).edit();
		editor.putBoolean(IDoegelConstants.FIRST_START, true);
		editor.commit();
	}

	public static synchronized boolean isFirstStart(Context context) {
		boolean erg = PreferenceManager.getDefaultSharedPreferences(context.getApplicationContext()).getBoolean(IDoegelConstants.FIRST_START, false);
		if (erg) {
			Editor editor = PreferenceManager.getDefaultSharedPreferences(context.getApplicationContext()).edit();
			editor.putBoolean(IDoegelConstants.FIRST_START, false);
			editor.commit();
		}
		return erg;
	}

	public static boolean isUserLogged(Context context) {
		return getUserRole(context) > 0;
	}

	@SuppressWarnings("unchecked")
	private static Class<Activity> getActivityClass(Context context, String name) {
		try {
			return (Class<Activity>) Class.forName(context.getPackageName() + "." + name);
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
		return null;
	}

	public static File getTemporaryImageFile(Context context) {
		return getTemporaryImageFile(context, "_image.png");
	}

	public static File getTemporaryImageFile(Context context, String filename) {
		return new File(Environment.getExternalStorageDirectory().toString(), context.getPackageName().replace('.', '_') + filename);
	}
}
